Release 10.1A: OpenEdge Development:
Progress 4GL Handbook


Dynamic programming tips

This section provides some advice on programming with dynamic objects.

Dynamic versus static programming

The most basic thing to consider about programming with dynamic objects is whether and when to do it at all. Since support for dynamic objects was added to the Progress 4GL in more recent releases, some developers think that dynamic constructs are inherently an improvement over their static counterparts and are tempted to program everything using dynamic objects. This is a big mistake. Dynamic objects are intended to give you more choices when you develop an application, not to replace static references to tables and fields. There are several important considerations:

So consider the power of dynamic programming for those situations where your application is doing the same thing in many places. Rather than writing many variations on the same source procedure or creating many compiled versions of the same procedure using include files or preprocessors, you can create a single procedure that does the same general job for every part of your application that needs it. This is why dynamic constructs exist. Consider their cost and the responsibility of having to clean up after yourself when you use them. Where they are the right thing to use, they can add tremendous flexibility to your application and dramatically reduce the number of different procedures you have to maintain.

Reusing dynamic objects

The major section of this chapter discusses Progress memory management and emphasizes that you must delete any dynamic objects you create. It’s important to keep in mind, however, that if you are going to create another dynamic object of the same type, especially inside a loop that is executed many times, it is much more efficient to reuse the same dynamic object rather than deleting it and re-creating it. This is true even if you change all the attributes of the object. Then you must simply remember to delete it after you are completely done with it.

For example, the following procedure needs to generate a dynamic buffer and a dynamic query for every table in the Sports2000 database. The information about tables, fields, and indexes is actually stored as schema information in the database itself, and you can access it the same way you do any other information. There are just a few bits of information you need to know to understand this example:

For each database table, the code creates a dynamic query and a dynamic buffer, and sets the query’s buffer to the dynamic buffer handle. Then the code prepares a default query for the table, opens it, gets the first record, and closes it. It then deletes the dynamic query and the dynamic buffer. To show the effect of the performance more dramatically, this is all done inside a loop 100 times. Figure 21–4 shows how long it took for one sample run.

Figure 21–4: Result of DELETE OBJECT example

There’s a more efficient way to do this. If you move the CREATE QUERY hQuery statement before the DO block and the FOR EACH block, and you move the DELETE OBJECT hQuery statement after the end of those blocks, the procedure runs somewhat faster. Even though you are resetting the query’s buffer and re-preparing it for a completely different buffer, it is still faster to reuse the same dynamic object:

/* h-DeleteObject.p */ 
DEFINE VARIABLE hQuery AS HANDLE      NO-UNDO. 
DEFINE VARIABLE hBuffer AS HANDLE     NO-UNDO. 
DEFINE VARIABLE iCount AS INTEGER     NO-UNDO. 
     
    CREATE QUERY hQuery. 
    ETIME(TRUE). 
    DO iCount = 1 TO 100: 
        FOR EACH _file WHERE _file-num > 0 AND _file-num < 32000: 
            CREATE BUFFER hBuffer FOR TABLE _file._file-name. 
            hQuery:SET-BUFFERS(hBuffer). 
            hQuery:QUERY-PREPARE("FOR EACH " + _file._file-name). 
            hQuery:QUERY-OPEN(). 
            hQuery:GET-FIRST(). 
            hQuery:QUERY-CLOSE(). 
            DELETE OBJECT hBuffer. 
        END. 
    END. 
    MESSAGE "100 iterations took " ETIME "milliseconds" VIEW-AS ALERT-BOX. 
    DELETE OBJECT hQuery. 

Figure 21–5 shows the result.

Figure 21–5: Result of more efficient DELETE OBJECT example

Just be sure you don’t forget to delete the object when you’re done with it! Unless you’re reusing the object a large number of times, the difference in performance won’t be dramatic, so it isn’t worth the risk of forgetting to delete a dynamic object unless you will be reusing it many times in succession.

Note that you can’t reuse the dynamic buffer in the same way. When you use the CREATE BUFFER statement, you must name the table the buffer will be for. This name can be an expression, as it is here, so that the buffer name can be assigned dynamically at run time, but you can’t then reuse that same dynamic buffer object for a different buffer. So you have to create it and delete it inside the loop.


Copyright © 2005 Progress Software Corporation
www.progress.com
Voice: (781) 280-4000
Fax: (781) 280-4095